home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include "wrend.h"
-
- /* 3D object translation, rotation, scaling, and animation
- Copyright 1995 Egerter Software */
-
-
-
- void set_object_pivot (object_3d *obj, float x, float y, float z)
- {
- obj->pivotx = x;
- obj->pivoty = y;
- obj->pivotz = z;
-
- obj->rotatex = 0;
- obj->rotatey = 0;
- obj->rotatez = 0;
-
- obj->scalex = 1;
- obj->scaley = 1;
- obj->scalez = 1;
- }
-
-
- void translate_object (object_3d *obj, vertex *pts, float x, float y, float z)
- {
- int start, finish;
- int poly, point;
- triangle_3d *ptr;
-
- /* Translate the center of each polygon */
- /*
- start = obj->start_poly;
- finish = obj->end_poly;
- for (poly = start; poly <= finish; poly++)
- {
- ptr = &polylist[poly];
- ptr->center.x += x;
- ptr->center.y += y;
- ptr->center.z += z;
- }
- */
- /* Translate each vertex in this object */
- start = obj->startpoints;
- finish = start + obj->points - 1;
-
- for (point = start; point <= finish; point++)
- {
- pts[point].local.x += x;
- pts[point].local.y += y;
- pts[point].local.z += z;
- }
-
- obj->pivotx += x;
- obj->pivoty += y;
- obj->pivotz += z;
- }
-
-
- void scale_object (object_3d *obj, vertex *pts, float x, float y, float z,
- float pivotx, float pivoty, float pivotz)
- {
- int start, finish;
- int point;
- vertex *pt;
-
- /* Translate each vertex in this object */
- start = obj->startpoints;
- finish = start + obj->points - 1;
-
- for (point = start; point <= finish; point++)
- {
- pt = &pts[point];
-
- pt->local.x = (pt->local.x - pivotx) * x + pivotx;
- pt->local.y = (pt->local.y - pivoty) * y + pivoty;
- pt->local.z = (pt->local.z - pivotz) * z + pivotz;
- }
-
- }
-
-
- void rotate_point (float *ptx, float *pty, float *ptz,
- float x, float y, float z,
- float pivotx, float pivoty, float pivotz)
- {
- float i,j,k;
- float rotx, roty, rotz;
- float xo, yo, zo;
- float xcos, xsin, ycos, ysin, zcos, zsin;
-
- xcos = cos (x * M_PI / 180.0);
- xsin = sin (x * M_PI / 180.0);
- ycos = cos (y * M_PI / 180.0);
- ysin = sin (y * M_PI / 180.0);
- zcos = cos (z * M_PI / 180.0);
- zsin = sin (z * M_PI / 180.0);
-
- xo = (*ptx) - pivotx;
- yo = (*pty) - pivoty;
- zo = (*ptz) - pivotz;
-
- /* Z axis */
- i = (xo * zcos - yo * zsin);
- j = (xo * zsin + yo * zcos);
- k = zo;
-
- /* X axis */
- roty = (j * xcos - k * xsin);
- rotz = (j * xsin + k * xcos);
- k = rotz;
-
- /* Y axis */
- rotx = (k * ysin + i * ycos);
- rotz = (k * ycos - i * ysin);
-
- *ptx = rotx + pivotx;
- *pty = roty + pivoty;
- *ptz = rotz + pivotz;
-
-
- }
-
-
-
-
- void rotate_object_with_children (object_3d *obj, vertex *pts, float x, float y, float z,
- float pivotx, float pivoty, float pivotz)
- {
- float i,j,k;
- float rotx, roty, rotz;
- int start, finish;
- int point, poly;
- float xo, yo, zo;
- float xcos, xsin, ycos, ysin, zcos, zsin;
- vertex *pt;
- triangle_3d *ptr;
- int child;
- object_3d *childptr;
-
- xcos = cos (x * M_PI / 180.0);
- xsin = sin (x * M_PI / 180.0);
- ycos = cos (y * M_PI / 180.0);
- ysin = sin (y * M_PI / 180.0);
- zcos = cos (z * M_PI / 180.0);
- zsin = sin (z * M_PI / 180.0);
-
- /* Rotate each vertex in this object */
- start = obj->startpoints;
- finish = start + obj->points - 1;
-
- for (point = start; point <= finish; point++)
- {
- /* Rotate the vertex */
- pt = &pts[point];
-
- xo = pt->local.x - pivotx;
- yo = pt->local.y - pivoty;
- zo = pt->local.z - pivotz;
-
- /* Z axis */
- i = (xo * zcos - yo * zsin);
- j = (xo * zsin + yo * zcos);
- k = zo;
-
- /* X axis */
- roty = (j * xcos - k * xsin);
- rotz = (j * xsin + k * xcos);
- k = rotz;
-
- /* Y axis */
- rotx = (k * ysin + i * ycos);
- rotz = (k * ycos - i * ysin);
-
- pt->local.x = rotx + pivotx;
- pt->local.y = roty + pivoty;
- pt->local.z = rotz + pivotz;
-
-
- /* Rotate the normal */
- xo = pt->normal.x;
- yo = pt->normal.y;
- zo = pt->normal.z;
-
- /* Z axis */
- i = (xo * zcos - yo * zsin);
- j = (xo * zsin + yo * zcos);
- k = zo;
-
- /* X axis */
- roty = (j * xcos - k * xsin);
- rotz = (j * xsin + k * xcos);
- k = rotz;
-
- /* Y axis */
- rotx = (k * ysin + i * ycos);
- rotz = (k * ycos - i * ysin);
-
- pt->normal.x = rotx;
- pt->normal.y = roty;
- pt->normal.z = rotz;
-
- }
-
-
- start = obj->start_poly;
- finish = obj->end_poly;
-
- for (poly = start; poly <= finish; poly++)
- {
- ptr = &polylist[poly];
-
- /* Rotate the normal of each polygon */
- xo = ptr->normal.x;
- yo = ptr->normal.y;
- zo = ptr->normal.z;
-
- /* Z axis */
- i = (xo * zcos - yo * zsin);
- j = (xo * zsin + yo * zcos);
- k = zo;
-
- /* X axis */
- roty = (j * xcos - k * xsin);
- rotz = (j * xsin + k * xcos);
- k = rotz;
-
- /* Y axis */
- rotx = (k * ysin + i * ycos);
- rotz = (k * ycos - i * ysin);
-
- ptr->normal.x = rotx;
- ptr->normal.y = roty;
- ptr->normal.z = rotz;
- }
-
-
- if (obj->maxchild > -1)
- {
- for (child = 0; child <= obj->maxchild; child++)
- {
- childptr = &objectlist[obj->children[child]];
- rotate_point (&childptr->pivotx, &childptr->pivoty, &childptr->pivotz,
- x, y, z, pivotx, pivoty, pivotz);
- rotate_object_with_children (childptr, pts, x, y, z, pivotx, pivoty,
- pivotz);
- }
- }
- }
-
-
- void rotate_object (object_3d *obj, vertex *pts, float x, float y, float z,
- float pivotx, float pivoty, float pivotz)
- {
- float i,j,k;
- float rotx, roty, rotz;
- int start, finish;
- int point, poly;
- float xo, yo, zo;
- float xcos, xsin, ycos, ysin, zcos, zsin;
- vertex *pt;
- triangle_3d *ptr;
-
- xcos = cos (x * M_PI / 180.0);
- xsin = sin (x * M_PI / 180.0);
- ycos = cos (y * M_PI / 180.0);
- ysin = sin (y * M_PI / 180.0);
- zcos = cos (z * M_PI / 180.0);
- zsin = sin (z * M_PI / 180.0);
-
-
- //obj->rotatex += x;
- //obj->rotatey += y;
- //obj->rotatez += z;
-
- /* Rotate each vertex in this object */
- start = obj->startpoints;
- finish = start + obj->points - 1;
-
- for (point = start; point <= finish; point++)
- {
- /* Rotate the vertex */
- pt = &pts[point];
-
- xo = pt->local.x - pivotx;
- yo = pt->local.y - pivoty;
- zo = pt->local.z - pivotz;
-
- /* Z axis */
- i = (xo * zcos - yo * zsin);
- j = (xo * zsin + yo * zcos);
- k = zo;
-
- /* X axis */
- roty = (j * xcos - k * xsin);
- rotz = (j * xsin + k * xcos);
- k = rotz;
-
- /* Y axis */
- rotx = (k * ysin + i * ycos);
- rotz = (k * ycos - i * ysin);
-
- pt->local.x = rotx + pivotx;
- pt->local.y = roty + pivoty;
- pt->local.z = rotz + pivotz;
-
-
- /* Rotate the normal */
- xo = pt->normal.x;
- yo = pt->normal.y;
- zo = pt->normal.z;
-
- /* Z axis */
- i = (xo * zcos - yo * zsin);
- j = (xo * zsin + yo * zcos);
- k = zo;
-
- /* X axis */
- roty = (j * xcos - k * xsin);
- rotz = (j * xsin + k * xcos);
- k = rotz;
-
- /* Y axis */
- rotx = (k * ysin + i * ycos);
- rotz = (k * ycos - i * ysin);
-
- pt->normal.x = rotx;
- pt->normal.y = roty;
- pt->normal.z = rotz;
-
- }
-
-
- start = obj->start_poly;
- finish = obj->end_poly;
-
- for (poly = start; poly <= finish; poly++)
- {
- ptr = &polylist[poly];
-
- /* Rotate the normal of each polygon */
- xo = ptr->normal.x;
- yo = ptr->normal.y;
- zo = ptr->normal.z;
-
- /* Z axis */
- i = (xo * zcos - yo * zsin);
- j = (xo * zsin + yo * zcos);
- k = zo;
-
- /* X axis */
- roty = (j * xcos - k * xsin);
- rotz = (j * xsin + k * xcos);
- k = rotz;
-
- /* Y axis */
- rotx = (k * ysin + i * ycos);
- rotz = (k * ycos - i * ysin);
-
- ptr->normal.x = rotx;
- ptr->normal.y = roty;
- ptr->normal.z = rotz;
- }
- }
-
-
-
- /* Considerations:
- - multiple keys per frame, for different objects
- - additive elements due to hierarchy
- - does scale affect children objects?
-
- - idea:
- - store additive amounts in object structure
- - for each keyframe, calculate new values and store
- into obj struct
-
- - for each frame of animation
- - set elements for each objects to 0
- - for each object,
- add elements from obj struct
- for each child of object
- add elements from parent
- - for each object
- transform if needed
-
-
-
- */
-
-
-
-
- void setup_nextframe (object_3d *obj)
- {
- int numframes;
- int searchframe;
- int frame;
- float tx, ty, tz, rx, ry, rz, sx, sy, sz;
- float cx, cy, cz;
- keydata *keyprev;
- keydata *key;
- int advance;
-
- advance = 0;
- frame = obj->currentframe;
-
- cx = obj->pivotx;
- cy = obj->pivoty;
- cz = obj->pivotz;
-
- key = &obj->keylist[frame];
- keyprev = key;
-
- if ((key->update_translation) && (obj->tstepsleft == -1))
- {
- searchframe = frame+1;
- while ((obj->keylist[searchframe].update_translation == 0)
- && (searchframe < obj->maxframe))
- searchframe++;
-
- if (obj->keylist[searchframe].update_translation == 1)
- {
- numframes = obj->keylist[searchframe].framenumber -
- obj->keylist[frame].framenumber;
- obj->tstepsleft = numframes;
-
- key = &obj->keylist[searchframe];
-
- tx = (key->tx - keyprev->tx) / numframes;
- ty = (key->ty - keyprev->ty) / numframes;
- tz = (key->tz - keyprev->tz) / numframes;
- obj->translatex = tx;
- obj->translatey = ty;
- obj->translatez = tz;
- advance = 1;
- }
- else
- if (obj->tstepsleft == 0)
- obj->tstepsleft = -1;
-
- }
- else
- {
- if (obj->tstepsleft == 0)
- obj->tstepsleft = -1;
- }
-
- /*if (key->update_scale)
- {
- sx = 1 + (key->sx / numframes);
- sy = 1 + (key->sy / numframes);
- sz = 1 + (key->sz / numframes);
- obj->scalex = sx;
- obj->scaley = sy;
- obj->scalez = sz;
- }*/
-
-
- if ((key->update_rotation) && (obj->rstepsleft == -1))
- {
- searchframe = frame+1;
- while ((obj->keylist[searchframe].update_rotation == 0)
- && (searchframe < obj->maxframe))
- searchframe++;
-
- if (obj->keylist[searchframe].update_rotation == 1)
- {
- numframes = obj->keylist[searchframe].framenumber -
- obj->keylist[frame].framenumber;
- obj->rstepsleft = numframes;
-
- key = &obj->keylist[searchframe];
-
- rx = (-key->rx) / numframes;
- ry = (-key->ry) / numframes;
- rz = (-key->rz) / numframes;
- obj->rotatex = rx;
- obj->rotatey = ry;
- obj->rotatez = rz;
- advance = 1;
- }
- else
- if (obj->rstepsleft == 0)
- obj->rstepsleft = -1;
-
- }
- else
- {
- if (obj->rstepsleft == 0)
- obj->rstepsleft = -1;
- }
-
- if (advance)
- {
- obj->currentframe++;
- if (obj->currentframe == obj->maxframe)
- obj->currentframe = 0;
- }
- }
-
-
- void animate_object (object_3d *obj, vertex *pts)
- {
- object_3d *obj2;
- object_3d *ch;
- int child;
- float px, py, pz, tx, ty, tz, rx, ry, rz, sx, sy, sz;
-
- px = obj->pivotx;
- py = obj->pivoty;
- pz = obj->pivotz;
- sx = obj->scalex;
- sy = obj->scaley;
- sz = obj->scalez;
- rx = obj->rotatex;
- ry = obj->rotatey;
- rz = obj->rotatez;
- tx = obj->translatex;
- ty = obj->translatey;
- tz = obj->translatez;
-
- /* if ((tx != 0) || (ty != 0) || (tz != 0))
- {
- translate_object (obj, pts, tx, ty, tz);
-
- obj2 = obj;
- while (obj2->numchildren > 0)
- {
- ch = &objectlist[obj2->children[0]];
- translate_object (ch, pts, tx, ty, tz);
- obj2 = ch;
- }
- }
- */
- /* if ((sx != 1) || (sy != 1) || (sz != 1))
- {
- scale_object (obj, pts, sx, sy, sz, px, py, pz);
- if (obj->numchildren > 0)
- for (child = 0; child < obj->numchildren; child++)
- scale_object (&objectlist[obj->children[child]], pts, sx, sy, sz, px, py, pz);
- }*/
-
- if ((rx != 0) || (ry != 0) || (rz != 0))
- {
- rotate_object_with_children (obj, pts, rx, ry, rz, px, py, pz);
- }
- }
-
-
-
- void animate_objects (vertex *pts)
- {
- int objnum; /* Object number */
- object_3d *obj; /* ptr to the object */
-
- for (objnum = 0; objnum < totalobjects; objnum++)
- {
- obj = &objectlist[objnum];
- if (obj->maxframe > -1)
- {
- if ((obj->tstepsleft < 0) || (obj->rstepsleft < 0))
- setup_nextframe (obj);
- if ((obj->tstepsleft > -1) || (obj->rstepsleft > -1))
- {
- animate_object (obj, pts);
- if (obj->tstepsleft >= 0)
- obj->tstepsleft--;
- if (obj->rstepsleft >= 0)
- obj->rstepsleft--;
- }
-
- }
- }
- }
-